﻿using Flurl.Http;
using Microsoft.Extensions.Options;
using Starry.Wx.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Starry.Wx.OAuth
{
    /// <summary>
    /// 微信OAuth登录API
    /// <para><see href="https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_Login/Authorized_API_call_UnionID.html" /></para>
    /// </summary>
    public class OAuthService : WxCoreService
    {
        public OAuthService(IOptions<WxOptions> options) : base(options)
        {
        }

        /// <summary>
        /// 获取AccessToken
        /// </summary>
        /// <param name="code">code作为换取access_token的票据，每次用户授权带上的code将不一样，code只能使用一次，5分钟未被使用自动过期。</param>
        /// <param name="grantType">填写为authorization_code（请保持默认参数）</param>
        /// <returns><see cref="AccessTokenResult"/></returns>
        /// <created>tanch,2021/4/4</created>
        /// <changed>tanch,2021/4/4</changed>
        public Task<AccessTokenResult> GetAccessTokenAsync(string code, string grantType = "authorization_code")
            => CallApiAsync<AccessTokenResult>($"/sns/oauth2/access_token?appid={base.AppId}&secret={base.AppSecret}&code={code}&grant_type={grantType}");

        /// <summary>
        /// 刷新（OAuth专用）access_token
        /// </summary>
        /// <param name="refreshToken">填写通过access_token获取到的refresh_token参数</param>
        /// <param name="grantType">填写为refresh_token（请保持默认参数）</param>
        /// <returns><see cref="AccessTokenResult"/></returns>
        /// <created>tanch,2021/4/5</created>
        /// <changed>tanch,2021/4/5</changed>
        public Task<AccessTokenResult> RefreshTokenAsync(string refreshToken, string grantType = "refresh_token")
            => CallApiAsync<AccessTokenResult>($"/sns/oauth2/refresh_token?appid={base.AppId}&grant_type={grantType}&refresh_token={refreshToken}");

        /// <summary>
        /// 获取用户基本信息
        /// </summary>
        /// <param name="oauthAccessToken">调用接口凭证（OAuth专用）</param>
        /// <param name="openId">普通用户的标识，对当前公众号唯一</param>
        /// <param name="lang">返回国家地区语言版本，zh_CN 简体，zh_TW 繁体，en 英语</param>
        /// <returns><see cref="UserInfoResult"/></returns>
        /// <created>tanch,2021/4/5</created>
        /// <changed>tanch,2021/4/5</changed>
        public Task<UserInfoResult> GetUserInfoAsync(string oauthAccessToken, string openId, string lang = "zh_CN")
            => CallApiAsync<UserInfoResult>($"/sns/userinfo?access_token={oauthAccessToken}&openid={openId}&lang={lang}");

        /// <summary>
        /// 检验授权凭证（access_token）是否有效（OAuth专用）
        /// </summary>
        /// <param name="oauthAccessToken">调用接口凭证（OAuth专用）</param>
        /// <param name="openId">用户的唯一标识</param>
        /// <returns><see cref="BaseResult"/></returns>
        /// <created>tanch,2021/4/5</created>
        /// <changed>tanch,2021/4/5</changed>
        public Task<BaseResult> AuthAsync(string oauthAccessToken, string openId)
            => CallApiAsync<BaseResult>($"/sns/auth?access_token={oauthAccessToken}&openid={openId}");


        /// <summary>
        /// 获取登录跳转地址
        /// </summary>
        /// <param name="redirectUrl">授权后重定向的回调链接地址，请使用urlencode对链接进行处理</param>
        /// <param name="state">重定向后会带上state参数，开发者可以填写a-zA-Z0-9的参数值，最多128字节</param>
        /// <param name="scope">应用授权作用域，snsapi_base （不弹出授权页面，直接跳转，只能获取用户openid），snsapi_userinfo （弹出授权页面，可通过openid拿到昵称、性别、所在地。并且，即使在未关注的情况下，只要用户授权，也能获取其信息）</param>
        /// <returns></returns>
        /// <created>tanch,2021/4/5</created>
        /// <changed>tanch,2021/4/5</changed>
        public string GetAuthorizeUrl(string redirectUrl, string state = "", string scope = "snsapi_userinfo")
            => $"https://open.weixin.qq.com/connect/oauth2/authorize?appid={base.AppId}&redirect_uri={WebUtility.UrlEncode(redirectUrl)}&response_type=code&scope={scope}&state={state}#wechat_redirect";
    }
}
